/**
 * 按块读写文件 fread, fwrite https://www.bilibili.com/video/BV1vs411n7TH?p=121
 */
#include <stdlib.h>
#include <string.h>
#include "../Utils/FileIOUtils.h"
#include "../entity/Student.h"

static const char *FILE_R_W = "../Read_Write_Test/6.读写2进制格式.txt";
static const enum StoryType {           //存储类型
    Int, Array, String, StringArray, Struct
};

void file_write_test();
void file_read_test();

static enum StoryType storeType;  //不能直接赋值, 否则有部分代码会变成灰色...
int main() {
    storeType = Struct;            //切换存储类型.

    //1.fwrite 二进制文件写
    file_write_test();
    //2.fread 二进制文件读
    file_read_test();

    return EXIT_SUCCESS;
}

//2.fwrite 二进制文件写
void file_write_test() {
//    FILE *file = file_open_wb(FILE_R_W);
    FILE *file = file_open_w(FILE_R_W);

    switch (storeType) {
        case Int: {
            //1.写入int
            int a = 5678;
            size_t len = file_write_binary(&a, sizeof(a), 1, file);
            printf("写入int a: %d, 实际成功写入文件的元素个数: %d\n", a, len);
        }
        break;
        case Array: {
            //2.写入字符数组
            char arr[] = "Hello爱的方式a\n";
            size_t len = file_write_binary(&arr, sizeof(char), sizeof(arr)/sizeof(char), file);
            printf("写入字符数组char arr[]: %s, 实际成功写入文件的元素个数: %d\n", arr, len);
        }
        break;
        case String: {
            //3.写入字符串
            char *arr = "Hello爱的方式a\n";
            size_t len = file_write_binary(&arr, sizeof(char), strlen(arr), file);
            printf("写入字符串char *arr: %s, 实际成功写入文件的元素个数: %d\n", arr, len);
        }
        break;
        case StringArray: {
            //4.写入字符串数组
            char *strs[2] = {"Hello爱的方式a\n", "数据的覅sdfsf是否sdf\n"};
            size_t len = file_write_binary(&strs, strlen(strs[0]), 2, file);
            printf("写入字符串数组char *strs[2], strs[0]: %s, strs[1]: %s, 实际成功写入文件的元素个数: %d\n", strs[0], strs[1], len);
        }
        break;
        case Struct: {
            //5.存储结构体数组
            struct Student stu[2] = {
                    {"张三", '1', 23, {77, 88}, NULL},
                    {"李四", '1', 24, {56, 78}, NULL}
            };
            size_t len = file_write_binary(&stu, sizeof(stu[0]), 2, file);
            printf("写入结构体数组struct Student stu[2], 实际成功写入文件的元素个数: %d\n", len);
        }
        break;
        default:
            break;
    }
    file_close(file);
}

//3.fread 二进制文件读
void file_read_test() {
    FILE *file = file_open_rb(FILE_R_W);

    switch (storeType) {
        case Int: {
            //1.读取int
            int a;
            size_t len = file_read_binary(&a, sizeof(a), 1, file);
            printf("读取int: %d, 实际成功读取文件的元素个数: %d\n", a, len);
        }
        break;
        case Array: {
            //2.读取字符数组
            char arr[100] = {0};
            size_t len = file_read_binary(&arr, sizeof(char), sizeof(arr)/sizeof(char), file);
            printf("读取字符数组char arr[]: %s, 实际成功读取文件的元素个数: %d\n", arr, len);
        }
        break;
        case String: {
            //3.读取字符串
            char *str;
            size_t len = file_read_binary(&str, sizeof(char), 999, file);
            printf("读取字符串char *str: %s, 实际成功读取文件的元素个数: %d\n", str, len);
        }
        break;
        case StringArray: {
            //4.读取字符串数组
            char *str[2];
            str[0] = malloc(sizeof(char) * 100);
            str[1] = malloc(sizeof(char) * 100);
            size_t len = file_read_binary(&str, sizeof(str[0]), 2, file);
            printf("读取字符串数组char *str[2], str[0]: %s, str[1]: %s, 实际成功读取文件的元素个数: %d\n", str[0], str[1], len);
            free(str[0]);
            free(str[1]);
        }
        break;
        case Struct: {
            //5.读取结构体数组
            struct Student *stus = malloc(sizeof(struct Student) * 2);

            //      ①.读出来有3个, 如果stus*2, 会报错崩溃.  stus*3才不会崩溃
//            int i = 0;
//            while (!file_eof(file)) {
//                size_t len3 = file_read_binary(&stus[i], sizeof(stus[0]), 1, file);
//                printStudent(stus[i]);
//                i++;
//            }

            //      ②.固定写死循环次数(可行)
//            for (int i = 0; i < 2; ++i) {
//                size_t len3 = file_read_binary(&stus[i], sizeof(stus[0]), 1, file);
//                printStudent(stus[i]);
//            }

/**                 ③.可行!    &stus在for循环会报错, 要写&stus[0] !!!
 *                  stus地址: 0061FEC0, stus[0]地址: 02BC1C58               */
            printf("stus地址: %p, stus[0]地址: %p\n", &stus, &stus[0]);
            size_t len = file_read_binary(&stus[0], sizeof(stus[0]), 2, file);
            printf("读取结构体数组struct Student *stus, 实际成功读取文件的元素个数: %d\n", len);
            for (int i = 0; i < len; ++i) {
                printStudent(stus[i]);
            }
            free(stus);
        }
        break;
        default:
            break;
    }

    file_close(file);
}